package opdr3a;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Random;


public class Console {
	private Connection connection;
	
	public Console() {
		connectionSetup();
		try {
			generateKlanten(10, 2012, 20, 10);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Maak verbinding met de database
	 */
	private void connectionSetup() {
		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
		} catch (ClassNotFoundException e1) {
			e1.printStackTrace();
		}
		
		try {
			connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL", "tthr", "oracle");
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Genereer alle klanten, berichten en gesprekken
	 * @param aantal Aantal klanten
	 * @param jaar Jaar warin ge-smst/gebeld wordt
	 * @throws SQLException
	 */
	private void generateKlanten(int aantal, int jaar, int max_berichten, int max_gesprekken) throws SQLException {
		for(int i = 0; i < aantal; i++) {
			String naam = "Arjan" + i;
			String mobiel_nr = randomNumber("0000000000");
			String rekening_nr = randomNumber("000000000000");
			insertBank(rekening_nr);
			int klant_id = insertKlant(naam, jaar, mobiel_nr, rekening_nr);
			
			int aantal_berichten = (int) (max_berichten * Math.random());
			for(int j = 0; j < aantal_berichten; j++) {
				insertSMS(klant_id, randomDatetime(jaar));
			}
			
			int aantal_gesprekken = (int) (max_gesprekken * Math.random());
			for(int j = 0; j < aantal_gesprekken; j++) {
				insertGesprek(klant_id, randomDatetime(jaar));
			}
		}
	}
	
	/**
	 * Insert een klant in de database
	 * @param naam
	 * @param jaar
	 * @param mobiel_nr
	 * @param rekening_nr
	 * @return Klant_id
	 * @throws SQLException
	 */
	private int insertKlant(String naam, int jaar, String mobiel_nr, String rekening_nr) throws SQLException {
		String sql = "INSERT INTO klantgegevens " +
				"(KLANT_ID,NAAM,GESLACHT,ADRES,WOONPLAATS,MOBIEL_NR,CONTRACT_START,CONTRACT_EIND,ABONNEMENT_ID,REKENING_NR) " +
				"VALUES (KLANTGEGEVENS_SEQ.nextval,'" + naam + "','m','Zernikeplein 11','Groningen'," +
				"'" + mobiel_nr + "',to_date('01-JAN-" + jaar + "','DD-MON-RR')," +
				"to_date('31-DEC-" + jaar + "','DD-MON-RR'),2,'" + rekening_nr + "')";
		Statement stmt = connection.createStatement();
		stmt.executeUpdate(sql);
		stmt.execute("SELECT KLANTGEGEVENS_SEQ.currval FROM dual");
		ResultSet rs = stmt.getResultSet();
		rs.next();
		int klant_id = rs.getInt(1);
		stmt.close();
		System.out.println(sql);
		return klant_id;
	}
	
	/**
	 * Genereer een willekeurige datum en tijd binnen het gegeven jaar
	 * @param jaar
	 * @return de willekeurige datum
	 */
	private Timestamp randomDatetime(int jaar) {
		long offset = Timestamp.valueOf(jaar + "-01-01 00:00:00").getTime();
		long end = Timestamp.valueOf(jaar + "-12-31 00:00:00").getTime();
		long diff = end - offset + 1;
		Timestamp rand = new Timestamp(offset + (long)(Math.random() * diff));
		return rand;
	}
	
	/**
	 * Voeg een rekening_nr aan de BANK tabel toe.
	 * @param rekening_nr
	 * @throws SQLException
	 */
	private void insertBank(String rekening_nr) throws SQLException {
		int saldo = 200;
		String sql = "INSERT INTO bank (REKENING_NR, SALDO) VALUES ('" + rekening_nr + "'," + saldo + ")";
		Statement stmt = connection.createStatement();
		stmt.executeUpdate(sql);
		stmt.close();
		System.out.println(sql);
	}
	
	/**
	 * Voeg een sms bericht toe aan de database
	 * @param klant_id
	 * @throws SQLException
	 */
	private void insertSMS(int klant_id, Timestamp datetime) throws SQLException {
		String inhoud = encode_sms("H0ee ,ok mejn goe ev nalgn?s");
		String sql = "INSERT INTO sms_bericht (BERICHT_ID,ONTVANGER_NR,INHOUD_ENCODED,VERSTUUR_DATETIME,KLANT_ID)" +
					" VALUES (SMS_BERICHT_SEQ.nextval,'0686546757','" + inhoud+ "',to_timestamp('" + datetime + "'," +
					"'YYYY-MM-DD hh24:mi:ss.ff')," + klant_id + ")";
		Statement stmt = connection.createStatement();
		stmt.executeUpdate(sql);
		stmt.close();
		System.out.println(sql);
	}
	
	private void insertGesprek(int klant_id, Timestamp datetime) throws SQLException {
		Timestamp gesprek_start = datetime;
		int sec = 40;
		Timestamp gesprek_einde = new Timestamp(gesprek_start.getTime() + sec * 1000);

		String ontvanger_nr = randomNumber("0000000000");
		String sql = "INSERT INTO gesprekken (GESPREK_ID,ONTVANGER_NR,GESPREK_START,GESPREK_EIND,KLANT_ID)" +
				"values (GESPREKKEN_SEQ.nextval,'" + ontvanger_nr + "',to_timestamp('" + gesprek_start + "','YYYY-MM-DD hh24:mi:ss.ff')," +
				"to_timestamp('" + gesprek_einde + "','YYYY-MM-DD hh24:mi:ss.ff')," + klant_id + ")";
		Statement stmt = connection.createStatement();
		stmt.executeUpdate(sql);
		stmt.close();
		System.out.println(sql);
	}
	
	/**
	 * De bericht wordt encoded. Dat gebeurt door de eerste teken met de tweede teken te verwisselen en derde met vierde teken etc.
	 * Bij een string met oneven lengte wordt er een 0 aan het begin van het bericht gezet.
	 * @param ongecodeerd bericht
	 * @return Het gecodeerde bericht 
	 */
	private String encode_sms(String message) {
		int lengte = message.length();
		if (lengte % 2 == 1) {
			message = "0" + message;
		}
		String newMessage =	"";
		for (int i=0; i < lengte; i+=2)	{
			newMessage = newMessage + message.charAt(i+1) + message.charAt(i);
		}
		return newMessage;
	}
	
	
	
	/**
	 * Genereer een random nummer. Wordt gebruikt om rekeningnummer en telefoon nummer te genereren.
	 * @param Formaat van de string. Bijvoorbeeld "0000000000" voor telefoon.
	 * @return
	 * @throws SQLException
	 */
	private String randomNumber(String format) {
		String number = null;
		String maxRand = format;
		maxRand.replace("0", "9");
		int maxRandInteger = Integer.parseInt(maxRand);
		Random rand = new Random(maxRandInteger);
		rand.setSeed(System.nanoTime());
		NumberFormat formatter = new DecimalFormat(format);	
		number = formatter.format(Math.abs(rand.nextInt()));
		return number;
	}

}
